package com.wzb.mybatisplus.bitaction.electrumaction.two;

import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;

public class CompressedPublicKeyToXY {

    public static void main(String[] args) {
        // 示例压缩公钥 (来自比特币测试网)
        String compressedPubKey = "02" + "1HLoD9E4SDFFPDiYfNYnkBLQ85Y51J3Zb1";

        try {
            ECPoint point = decompressPublicKey(compressedPubKey);

            // 获取坐标
            BigInteger x = point.getAffineXCoord().toBigInteger();
            BigInteger y = point.getAffineYCoord().toBigInteger();

            System.out.println("从压缩公钥推出的坐标:");
            System.out.println("X: " + x.toString(16).toUpperCase());
            System.out.println("Y: " + y.toString(16).toUpperCase());

            // 验证：将坐标转换回压缩格式，应该与原始输入一致
            String recompressed = compressPublicKey(x, y);
            System.out.println("重新压缩验证: " + recompressed.equals(compressedPubKey));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从压缩公钥解压出ECPoint
     */
    public static ECPoint decompressPublicKey(String compressedKey) {
        try {
            // 获取secp256k1曲线参数
            ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");

            // 将十六进制字符串转换为字节数组
            byte[] pubKeyBytes = hexStringToByteArray(compressedKey);

            // 从字节数组解码点（自动处理压缩格式）
            ECPoint point = spec.getCurve().decodePoint(pubKeyBytes);

            return point;
        } catch (Exception e) {
            throw new RuntimeException("解压公钥失败", e);
        }
    }

    /**
     * 将坐标压缩回公钥格式
     */
    public static String compressPublicKey(BigInteger x, BigInteger y) {
        ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");

        // 创建点
        ECPoint point = spec.getCurve().createPoint(x, y);

        // 获取压缩格式的字节数组（前缀为0x02或0x03）
        byte[] compressed = point.getEncoded(true);

        return byteArrayToHexString(compressed).toUpperCase();
    }

    /**
     * 十六进制字符串转字节数组
     */
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    /**
     * 字节数组转十六进制字符串
     */
    public static String byteArrayToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}
